package com.neuedu.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JdbcUtil {
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String URL = "jdbc:mysql://192.168.80.191:3306/tailidb?serverTimezone=Asia/Shanghai";
    private static final String USER = "root";
    private static final String PASSWORD = "123456";
    static {
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    public static void close(Connection con, PreparedStatement pstmt) {
        try {
            if (null != pstmt)
                pstmt.close();
            if (null != con)
                con.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static void close(Connection con, PreparedStatement pstmt, ResultSet rs) {
        try {
            if (null != rs)
                rs.close();
            close(con, pstmt);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static Connection getConnection () throws SQLException {
        return DriverManager.getConnection(URL, USER, PASSWORD);
    }

    /**
     *  查询不同的表 返回的List<泛型> 泛型不同
     *  对于ResultSet处理的方式不同
     *      但是做的事一样
     *          创建对象  该对象的类型 和 泛型一致
     *          为属性赋值
     *          放进list
     *
     * */
    public static <T> List<T> executeQuery(String sql, Class<T> clz, Object... params) {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<T> list = new ArrayList<>();
        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            if (null != params) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            rs = pstmt.executeQuery();
            while (rs.next()) {
                T t = clz.getConstructor().newInstance();
                Field[] fields = clz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    field.set(t, rs.getObject(field.getName()));
                }
                list.add(t);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } finally {
            close(con, pstmt, rs);
        }
        return list;
    }
    public static int executeUpdate(String sql, Object... params) {
        Connection con = null;
        PreparedStatement pstmt = null;
        int result = 0;
        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            if (null != params) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            result = pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            close(con, pstmt);
        }
        return result;
    }
    public static <T> T executeQueryOne(String sql, Class<T> clz, Object... params) {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        T t = null;
        try {
            con = getConnection();
            pstmt = con.prepareStatement(sql);
            if (null != params) {
                for (int i = 0; i < params.length; i++) {
                    pstmt.setObject(i + 1, params[i]);
                }
            }
            rs = pstmt.executeQuery();
            if (rs.next()) {
                t = clz.getConstructor().newInstance();
                Field[] fields = clz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    field.set(t, rs.getObject(field.getName()));
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } finally {
            close(con, pstmt, rs);
        }
        return t;
    }
}
